package com.wyzz.hr.util;

import java.io.PrintStream;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.hibernate.criterion.*;
import org.springframework.util.ObjectUtils;

import com.wyzz.hr.bo.IDepartmentBO;
import com.wyzz.hr.bo.impl.ExaminDateUtil;
import com.wyzz.hr.pojo.Department;
import com.wyzz.hr.pojo.Employee;
import com.wyzz.hr.pojo.PositionBase;
import com.wyzz.hr.spring.SpringBeanFactory;
import com.wyzz.hr.util.reflect.ObjectProperty;

public class BaseCrit {

	public BaseCrit() {
	}

	public static void addDC(DetachedCriteria dc, String alias, String op,
			String argS[]) {
		if (StringUtils.isEmpty(alias) || StringUtils.isEmpty(op)
				|| argS == null || StringUtils.isEmpty(argS[0])
				|| ",".equals(argS[0].trim())) {
			return;
		} else {
			dc.add(addC(alias, op, argS));
			return;
		}
	}

	public static Criterion addC(String alias, String op, String argS[]) {
		if (op == "like")
			return Restrictions.ilike(alias, (new StringBuilder()).append("%")
					.append(argS[0].trim().replace("\u3000", "")).append("%")
					.toString());
		if (op == "eq")
			return Restrictions.eq(alias, argS[0].trim().replace("\u3000", ""));
		if (op == "ge")
			return Restrictions.ge(alias, argS[0].trim().replace("\u3000", ""));
		if (op == "gt")
			return Restrictions.gt(alias, argS[0].trim().replace("\u3000", ""));
		if (op == "le")
			return Restrictions.le(alias, argS[0].trim().replace("\u3000", ""));
		if (op == "lt")
			return Restrictions.lt(alias, argS[0].trim().replace("\u3000", ""));
		if (op == "between")
			return Restrictions.between(alias, argS[0].trim().replace("\u3000",
					""), argS[1]);
		if (op == "in")
			return Restrictions.in(alias, argS);
		else
			return null;
	}

	public static void addDC(DetachedCriteria dc, String alias, String op,
			Integer argI[]) {
		if (op == "between") {
			if (argI[0] == null && argI[1] == null)
				return;
			if (argI[0] == null)
				argI[0] = new Integer(0xc4653601);
			if (argI[1] == null)
				argI[1] = new Integer(0x3b9ac9ff);
		}
		if (StringUtils.isEmpty(alias) || StringUtils.isEmpty(op)
				|| argI == null || argI[0] == null) {
			return;
		} else {
			dc.add(addC(alias, op, argI));
			return;
		}
	}

	public static Criterion addC(String alias, String op, Integer argI[]) {
		if (op == "eq")
			return Restrictions.eq(alias, argI[0]);
		if (op == "ge")
			return Restrictions.ge(alias, argI[0]);
		if (op == "gt")
			return Restrictions.gt(alias, argI[0]);
		if (op == "le")
			return Restrictions.le(alias, argI[0]);
		if (op == "lt")
			return Restrictions.lt(alias, argI[0]);
		if (op == "between")
			return Restrictions.between(alias, argI[0], argI[1]);
		if (op == "in")
			return Restrictions.in(alias, argI);
		else
			return null;
	}

	public static void addDC(DetachedCriteria dc, String alias, String op,
			BigDecimal argBD[]) {
		if (op == "between") {
			if (argBD[0] == null && argBD[1] == null)
				return;
			if (argBD[0] == null)
				argBD[0] = new BigDecimal(-99999999999.990005D);
			if (argBD[1] == null)
				argBD[1] = new BigDecimal(99999999999.990005D);
		}
		if (StringUtils.isEmpty(alias) || StringUtils.isEmpty(op)
				|| argBD == null || argBD[0] == null) {
			return;
		} else {
			dc.add(addC(alias, op, argBD));
			return;
		}
	}

	public static Criterion addC(String alias, String op, BigDecimal argBD[]) {
		if (op == "eq")
			return Restrictions.eq(alias, argBD[0]);
		if (op == "ge")
			return Restrictions.ge(alias, argBD[0]);
		if (op == "gt")
			return Restrictions.gt(alias, argBD[0]);
		if (op == "le")
			return Restrictions.le(alias, argBD[0]);
		if (op == "lt")
			return Restrictions.lt(alias, argBD[0]);
		if (op == "between")
			return Restrictions.between(alias, argBD[0], argBD[1]);
		if (op == "in")
			return Restrictions.in(alias, argBD);
		else
			return null;
	}

	public static void addDC(DetachedCriteria dc, String alias, String op,
			Date argD[]) {
		if (op == "between") {
			if (argD[0] == null && argD[1] == null)
				return;
			if (argD[0] == null)
				argD[0] = new Date(1898L);
			if (argD[1] == null)
				argD[1] = new Date(9997L);
		}
		if (StringUtils.isEmpty(alias) || StringUtils.isEmpty(op)
				|| argD == null || argD[0] == null)
			return;
		if (argD[1] == null)
			dc.add(addC(alias, op, argD));
	}

	public static Criterion addC(String alias, String op, Date argD[]) {
		if (op == "between") {
			if (argD[0] == null)
				argD[0] = new Date(1898L);
			if (argD[1] == null)
				argD[1] = new Date(9997L);
		}
		if (op == "eq")
			return Restrictions.eq(alias, argD[0]);
		if (op == "ge")
			return Restrictions.ge(alias, argD[0]);
		if (op == "gt")
			return Restrictions.gt(alias, argD[0]);
		if (op == "le")
			return Restrictions.le(alias, argD[0]);
		if (op == "lt")
			return Restrictions.lt(alias, argD[0]);
		if (op == "between")
			return Restrictions.between(alias, argD[0], argD[1]);
		if (op == "in")
			return Restrictions.in(alias, argD);
		else
			return null;
	}

	public static void addDCDate(DetachedCriteria dc, String alias, String op,
			Date argD[]) {
		if (op == "between") {
			if (argD[0] == null && argD[1] == null)
				return;
			if (argD[0] == null)
				argD[0] = new Date(1898L);
			if (argD[1] == null)
				argD[1] = new Date(9997L);
		}
		if (StringUtils.isEmpty(alias) || StringUtils.isEmpty(op)
				|| argD == null || argD[0] == null) {
			return;
		} else {
			dc.add(addCDate(alias, op, argD));
			return;
		}
	}

	public static void addDCDateRange(DetachedCriteria dc, String alias,
			Date dLow, Date dHigh) {
		if (StringUtils.isEmpty(alias))
			return;
		if (dLow != null && dHigh != null)
			dc.add(addCDate(alias, "between", new Date[] { dLow, dHigh }));
		else if (dLow != null)
			dc.add(addCDate(alias, "ge", new Date[] { dLow }));
		else if (dHigh != null)
			dc.add(addCDate(alias, "le", new Date[] { dHigh }));
	}

	public static void addDCTwoDateRange(DetachedCriteria dc, String alias[],
			Date startDate, Date endDate) {
		if (alias == null || alias.length != 2)
			return;
		if (StringUtils.isEmpty(alias[0]) || StringUtils.isEmpty(alias[1]))
			return;
		if (startDate == null && endDate == null)
			return;
		Criterion tempC = null;
		if (startDate == null && endDate != null)
			tempC = Restrictions.or(Restrictions.and(Restrictions
					.isNotNull(alias[0]), Restrictions.le(alias[0], endDate)),
					Restrictions.and(Restrictions.isNull(alias[0]),
							Restrictions.isNotNull(alias[1])));
		else if (startDate != null && endDate != null)
			tempC = Restrictions.or(Restrictions.and(Restrictions
					.isNotNull(alias[0]), Restrictions.and(Restrictions
					.isNull(alias[1]), Restrictions.le(alias[0], endDate))),
					Restrictions.or(Restrictions.and(Restrictions
							.isNull(alias[0]), Restrictions.and(Restrictions
							.isNotNull(alias[1]), Restrictions.ge(alias[1],
							startDate))), Restrictions.not(Restrictions.or(
							Restrictions.gt(alias[0], endDate), Restrictions
									.lt(alias[1], startDate)))));
		else if (endDate == null && startDate != null)
			tempC = Restrictions.or(
					Restrictions.and(Restrictions.isNotNull(alias[1]),
							Restrictions.ge(alias[1], startDate)), Restrictions
							.and(Restrictions.isNull(alias[1]), Restrictions
									.isNotNull(alias[0])));
		dc.add(tempC);
	}

	public static void addDCDateExpire(DetachedCriteria dc, String alias,
			String op, Integer offsetDays, Date dCurr) {
		if (StringUtils.isEmpty(alias))
			return;
		if (dCurr == null)
			dCurr = new Date();
		Date dLow = dCurr;
		Date dHigh = dCurr;
		if (offsetDays != null)
			dHigh = DateUtil.dateAdd(dLow, offsetDays.intValue());
		if ("le".equals(op))
			dc.add(addCDate(alias, "le", new Date[] { dHigh }));
		else
			dc.add(addCDate(alias, "between", new Date[] { dLow, dHigh }));
	}

	public static Criterion addCDate(String alias, String op, Date argD[]) {
		if (op == "between") {
			if (argD[0] == null)
				argD[0] = new Date(1898L);
			if (argD[1] == null)
				argD[1] = new Date(9997L);
		}
		for (int i = 0; i < argD.length; i++)
			argD[i] = DateUtil.convDateTimeToDate(argD[i]);

		if (op == "eq")
			return Restrictions.eq(alias, argD[0]);
		if (op == "ge")
			return Restrictions.ge(alias, argD[0]);
		if (op == "gt")
			return Restrictions.gt(alias, argD[0]);
		if (op == "le")
			return Restrictions.le(alias, argD[0]);
		if (op == "lt")
			return Restrictions.lt(alias, argD[0]);
		if (op == "between")
			return Restrictions.between(alias, argD[0], argD[1]);
		if (op == "in")
			return Restrictions.in(alias, argD);
		else
			return null;
	}

	public static void addDCObjIds(DetachedCriteria dc, String alias,
			String propId, String argS[]) {
		if (StringUtils.isEmpty(alias) || StringUtils.isEmpty(propId)
				|| argS == null || argS.length == 0)
			return;
		if (argS.length == 1)
			dc.add(addC((new StringBuilder()).append(alias).append(".").append(
					propId).toString(), "eq", argS));
		else if (argS.length > 1)
			dc.add(addC((new StringBuilder()).append(alias).append(".").append(
					propId).toString(), "in", argS));
	}

	public static void addDC(DetachedCriteria dc, String alias, String propId,
			Object argO[]) {
		if (StringUtils.isEmpty(alias) || argO == null || argO[0] == null)
			return;
		if (argO.length == 1) {
			try {
				String idValue = (String) ObjectProperty
						.getObjectFinalProperty(argO[0], propId);
				if (StringUtils.isEmpty(idValue))
					return;
			} catch (Exception ex) {
				System.out.println((new StringBuilder()).append(
						"==========error: cannot convert object key").append(
						((Object) (argO))).toString());
				return;
			}
			dc.add(addC(alias, "eq", argO));
		}
		if (argO.length > 1)
			dc.add(addC(alias, "in", argO));
	}

	public static Criterion addC(String alias, String op, Object argO[]) {
		try {
			if (op == "eq")
				return Restrictions.eq(alias, argO[0]);
		} catch (Exception ex) {
			System.out.println((new StringBuilder()).append(
					"==========error: cannot convert object").append(argO[0])
					.toString());
			return null;
		}
		if (op == "in")
			return Restrictions.in(alias, argO);
		return null;
	}

	public static void addOrgDC(DetachedCriteria dc, String alias,
			String argDepts[], String argLocs[]) {
		if ((argDepts == null || argDepts.length == 0)
				&& (argLocs == null || argLocs.length == 0))
			return;
		if (!StringUtils.isEmpty(alias))
			alias = (new StringBuilder()).append(alias).append(".").toString();
		else
			alias = "";
		dc.add(addOrgC(alias, argDepts, argLocs));
	}

	public static Criterion addOrgC(String alias, String argDepts[],
			String argLocs[]) {
		if (argLocs == null || argLocs.length == 0)
			return Restrictions.in((new StringBuilder()).append(alias).append(
					Employee.PROP_EMP_DEPT_NO).append(".id").toString(),
					argDepts);
		if (argDepts == null || argDepts.length == 0)
			return Restrictions.in((new StringBuilder()).append(alias).append(
					Employee.PROP_EMP_LOCATION_NO).append(".id").toString(),
					argLocs);
		else
			return Restrictions.disjunction().add(
					Restrictions.in(
							(new StringBuilder()).append(alias).append(
									Employee.PROP_EMP_DEPT_NO).append(".id")
									.toString(), argDepts)).add(
					Restrictions.in((new StringBuilder()).append(alias).append(
							Employee.PROP_EMP_LOCATION_NO).append(".id")
							.toString(), argLocs));
	}

	public static void addDeptDC(DetachedCriteria dc, String aliasDept,
			String aliasPB, Integer status, Department dept) {
		if (dept == null || StringUtils.isEmpty(dept.getId())
				|| StringUtils.isEmpty(aliasDept))
			return;
		String argS[] = new String[3];
		argS = dept.getId().split(",");
		if (StringUtils.isEmpty(argS[0]))
			return;
		if (!StringUtils.isEmpty(argS[1]))
			addDC(dc, (new StringBuilder()).append(aliasPB).append(".").append(
					PositionBase.PROP_ID).toString(), "eq",
					new String[] { argS[1] });
		else if ("1".equals(argS[2])) {
			IDepartmentBO deptBo = (IDepartmentBO) SpringBeanFactory
					.getBean("departmentBO");
			List deptsInCharge = deptBo.getAllSubDepts(status,
					new String[] { argS[0] });
			addDC(dc, aliasDept, Department.PROP_ID, deptsInCharge.toArray());
		} else {
			addDC(dc, (new StringBuilder()).append(aliasDept).append(".")
					.append(Department.PROP_ID).toString(), "eq",
					new String[] { argS[0] });
		}
	}

	public static void addEmpDC(DetachedCriteria dc, String alias, String argS) {
		if (StringUtils.isEmpty(argS))
			return;
		if (!StringUtils.isEmpty(alias))
			alias = (new StringBuilder()).append(alias).append(".").toString();
		else
			alias = "";
		dc.add(addEmpC(alias, argS.trim().replace("\u3000", "")));
	}

	public static Criterion addEmpC(String alias, String argS) {
		return Restrictions.disjunction().add(
				Restrictions.ilike((new StringBuilder()).append(alias).append(
						Employee.PROP_EMP_DISTINCT_NO).toString(),
						(new StringBuilder()).append("%").append(argS).append(
								"%").toString())).add(
				Restrictions.ilike((new StringBuilder()).append(alias).append(
						Employee.PROP_EMP_NAME).toString(),
						(new StringBuilder()).append("%").append(argS).append(
								"%").toString()));
	}

	public static void addDeptEmpDC(DetachedCriteria dc, String alias,
			String argS) {
		if (StringUtils.isEmpty(argS))
			return;
		if (!StringUtils.isEmpty(alias))
			alias = (new StringBuilder()).append(alias).append(".").toString();
		else
			alias = "";
		dc.add(addDeptEmpC(alias, argS.trim().replace("\u3000", "")));
	}

	public static Criterion addDeptEmpC(String alias, String argS) {
		return Restrictions.disjunction().add(
				Restrictions.ilike((new StringBuilder()).append(alias).append(
						Employee.PROP_EMP_DEPT_NO).append(".").append(
						Department.PROP_DEPARTMENT_NAME).toString(),
						(new StringBuilder()).append("%").append(argS).append(
								"%").toString())).add(
				Restrictions.ilike((new StringBuilder()).append(alias).append(
						Employee.PROP_EMP_DISTINCT_NO).toString(),
						(new StringBuilder()).append("%").append(argS).append(
								"%").toString())).add(
				Restrictions.ilike((new StringBuilder()).append(alias).append(
						Employee.PROP_EMP_NAME).toString(),
						(new StringBuilder()).append("%").append(argS).append(
								"%").toString()));
	}

	public static void addStatusEmpDC(DetachedCriteria dc, String alias,
			String yearmonth, String argS[]) {
		if (StringUtils.isEmpty(yearmonth))
			return;
		if (!StringUtils.isEmpty(alias))
			alias = (new StringBuilder()).append(alias).append(".").toString();
		else
			alias = "";
		Criterion crit = addStatusEmpC(alias, yearmonth, argS);
		if (crit != null)
			dc.add(crit);
	}

	public static Criterion addStatusEmpC(String alias, String yearmonth,
			String argS[]) {
		String config = DatabaseSysConfigManager.getInstance().getProperty(
				"sys.examin.month.sum");
		Date dateArr[] = ExaminDateUtil.getDateArray(yearmonth, config);
		if (ObjectUtils.isEmpty(argS) || StringUtils.isEmpty(argS[0]))
			return Restrictions.disjunction().add(
					Restrictions.and(Restrictions.le((new StringBuilder())
							.append(alias).append(Employee.PROP_EMP_JOIN_DATE)
							.toString(), dateArr[1]), Restrictions.eq(
							(new StringBuilder()).append(alias).append(
									Employee.PROP_EMP_STATUS).toString(),
							Integer.valueOf(1)))).add(
					Restrictions.ge((new StringBuilder()).append(alias).append(
							Employee.PROP_EMP_TERMINATE_DATE).toString(),
							dateArr[0]));
		if ("newIn".equals(argS[0]))
			return addCDate((new StringBuilder()).append(alias).append(
					Employee.PROP_EMP_JOIN_DATE).toString(), "between", dateArr);
		if ("newOut".equals(argS[0]))
			return addCDate((new StringBuilder()).append(alias).append(
					Employee.PROP_EMP_TERMINATE_DATE).toString(), "between",
					dateArr);
		if ("normal".equals(argS[0]))
			return Restrictions.disjunction().add(
					Restrictions
							.lt((new StringBuilder()).append(alias).append(
									Employee.PROP_EMP_JOIN_DATE).toString(),
									dateArr[0])).add(
					Restrictions.gt((new StringBuilder()).append(alias).append(
							Employee.PROP_EMP_TERMINATE_DATE).toString(),
							dateArr[1]));
		else
			return null;
	}

	public static void addEmpEngDC(DetachedCriteria dc, String alias,
			String argS) {
		if (StringUtils.isEmpty(argS))
			return;
		if (!StringUtils.isEmpty(alias))
			alias = (new StringBuilder()).append(alias).append(".").toString();
		else
			alias = "";
		dc.add(addEmpEngC(alias, argS.trim().replace("\u3000", "")));
	}

	public static Criterion addEmpEngC(String alias, String argS) {
		return Restrictions.disjunction().add(
				Restrictions.ilike((new StringBuilder()).append(alias).append(
						Employee.PROP_EMP_DISTINCT_NO).toString(),
						(new StringBuilder()).append("%").append(argS).append(
								"%").toString())).add(
				Restrictions.ilike((new StringBuilder()).append(alias).append(
						Employee.PROP_EMP_NAME).toString(),
						(new StringBuilder()).append("%").append(argS).append(
								"%").toString())).add(
				Restrictions.ilike((new StringBuilder()).append(alias).append(
						Employee.PROP_EMP_FNAME).toString(),
						(new StringBuilder()).append("%").append(argS).append(
								"%").toString())).add(
				Restrictions.ilike((new StringBuilder()).append(alias).append(
						Employee.PROP_EMP_MNAME).toString(),
						(new StringBuilder()).append("%").append(argS).append(
								"%").toString())).add(
				Restrictions.ilike((new StringBuilder()).append(alias).append(
						Employee.PROP_EMP_LNAME).toString(),
						(new StringBuilder()).append("%").append(argS).append(
								"%").toString()));
	}

	static final int splitIn = 500;
}
